package com.whj.serviceprice.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.whj.internalcommon.constant.CommonStatusEnum;
import com.whj.internalcommon.dto.PriceRules;
import com.whj.internalcommon.dto.ResponseResult;
import com.whj.internalcommon.request.ForecastPriceDTO;
import com.whj.internalcommon.response.DirectionResponse;
import com.whj.internalcommon.response.ForecastPriceResponse;
import com.whj.internalcommon.utils.BigDecimalUtils;
import com.whj.serviceprice.mapper.PriceRulesMapper;
import com.whj.serviceprice.remote.ServiceMapClient;
import com.whj.serviceprice.service.PriceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;

/**
 * @Auther: wanghaijun
 * @Date: 2023/1/6 - 01 - 06 - 13:46 
 * @Description: com.whj.serviceprice.service.impl
 */

@Service
@Slf4j
public class PriceServiceImpl implements PriceService {

    @Autowired
    private ServiceMapClient serviceMapClient;

    @Autowired
    private PriceRulesMapper priceRulesMapper;

    /**
     * 根据经纬度 城市编码，车辆类型来计算价格
     *
     * @param depLongitude
     * @param depLatitude
     * @param desLongitude
     * @param desLatitude
     * @param cityCode
     * @param vehicleType
     * @return
     */
    @Override
    public ResponseResult forecastPrice(String depLongitude, String depLatitude, String desLongitude,
                                        String desLatitude, String cityCode,String vehicleType) {

        log.info("出发地经度:" + depLongitude);
        log.info("出发地纬度:" + depLatitude);
        log.info("目的地经度:" + desLongitude);
        log.info("目的地纬度:" + desLatitude);

        log.info("调用地图服务，查询距离和时长");
        ForecastPriceDTO forecastPriceDTO = new ForecastPriceDTO();
        forecastPriceDTO.setDepLongitude(depLongitude);
        forecastPriceDTO.setDepLatitude(depLatitude);
        forecastPriceDTO.setDesLongitude(desLongitude);
        forecastPriceDTO.setDesLatitude(desLatitude);
        ResponseResult<DirectionResponse> driving = serviceMapClient.driving(forecastPriceDTO);
        Integer duration = driving.getData().getDuration();
        Integer distance = driving.getData().getDistance();

        log.info("距离：" + distance + "时长：" + duration);

        log.info("读取计价规则");

        QueryWrapper<PriceRules> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("city_code", cityCode);
        queryWrapper.eq("vehicle_type", vehicleType);
        queryWrapper.orderByDesc("fare_version");

        List<PriceRules> priceRules = priceRulesMapper.selectList(queryWrapper);

        //计价规则不存在
        if (priceRules.size() == 0) {
            return ResponseResult.fail(CommonStatusEnum.PRICE_RULE_EMPTY.getCode(), CommonStatusEnum.PRICE_RULE_EMPTY.getValue());
        }

        PriceRules priceRule = priceRules.get(0);

        log.info("根据距离、时长和计价规则，计算价格");
        double price = getPrice(distance, duration, priceRule);

        ForecastPriceResponse forecastPriceResponse = new ForecastPriceResponse();
        forecastPriceResponse.setPrice(price);
        forecastPriceResponse.setCityCode(cityCode);
        forecastPriceResponse.setVehicleType(vehicleType);
        forecastPriceResponse.setFareType(priceRule.getFareType());
        forecastPriceResponse.setFareVersion(priceRule.getFareVersion());
        return ResponseResult.success(forecastPriceResponse);

    }

    /**
     * 计算实际价格
     *
     * @param distance
     * @param duration
     * @param cityCode
     * @param vehicleType
     * @return
     */
    @Override
    public ResponseResult<Double> calculatePrice(Integer distance, Integer duration, String cityCode, String vehicleType) {

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("city_code", cityCode);
        queryWrapper.eq("vehicle_type", vehicleType);
        queryWrapper.orderByDesc("fare_version");

        List<PriceRules> priceRules = priceRulesMapper.selectList(queryWrapper);

        //计价规则不存在
        if (priceRules.size() == 0) {
            return ResponseResult.fail(CommonStatusEnum.PRICE_RULE_EMPTY.getCode(), CommonStatusEnum.PRICE_RULE_EMPTY.getValue());
        }
        PriceRules priceRule = priceRules.get(0);

        log.info("根据距离、时长和计价规则，计算价格");
        double price = getPrice(distance, duration, priceRule);
        return ResponseResult.success(price);
    }


    /**
     * 根据距离、时常和计价规则计算价格
     *
     * @param distance  距离
     * @param duration  时长
     * @param priceRule 计价规则
     * @return
     */
    public double getPrice(Integer distance, Integer duration, PriceRules priceRule) {

        double price = 0;

        // 起步价
        double startFare = priceRule.getStartFare();
        price = BigDecimalUtils.add(price,startFare);

        // 里程费
        // 总里程 m 转化为km
        double distanceMile = BigDecimalUtils.divide(distance,1000);
        // 起步里程
        double startMile = (double)priceRule.getStartMile();
        // 实际里程 = 总里程-起步里程
        double distanceSubtract = BigDecimalUtils.substract(distanceMile,startMile);
        // 最终收费的里程数 km
        double mile = distanceSubtract<0?0:distanceSubtract;
        // 计程单价 元/km
        double unitPricePerMile = priceRule.getUnitPricePerMile();
        // 里程价格 = 最终里程*计程单价
        double mileFare = BigDecimalUtils.multiply(mile,unitPricePerMile);
        price = BigDecimalUtils.add(price,mileFare);

        // 时长费
        // 时长的分钟数
        double timeMinute = BigDecimalUtils.divide(duration,60);
        // 计时单价
        double unitPricePerMinute = priceRule.getUnitPricePerMinute();

        // 时长费用 = 时长单价* 时长分钟
        double timeFare = BigDecimalUtils.multiply(timeMinute,unitPricePerMinute);
        price = BigDecimalUtils.add(price,timeFare);

        BigDecimal priceBigDecimal = new BigDecimal(price);
        priceBigDecimal = priceBigDecimal.setScale(2,BigDecimal.ROUND_HALF_UP);

        return priceBigDecimal.doubleValue();
    }

    public static void main(String[] args) {

        PriceRules priceRules = new PriceRules();
        priceRules.setStartFare(10.0);
        priceRules.setStartMile(3);
        priceRules.setUnitPricePerMile(1.8);
        priceRules.setUnitPricePerMinute(0.5);

        // System.out.println("getPrice(6500,1800,priceRules) = " + getPrice(6500, 1800, priceRules));
    }
}
